package cn.getech.data.metadata.service.impl;

import cn.getech.data.development.entity.TableRelationshipEntity;
import cn.getech.data.metadata.constant.MetaTableTypeEnum;
import cn.getech.data.metadata.constant.YesOrNoEnum;
import cn.getech.data.metadata.controller.blood.BloodNode;
import cn.getech.data.metadata.controller.blood.BloodShip;
import cn.getech.data.metadata.controller.blood.BloodUnion;
import cn.getech.data.metadata.controller.module.ModuleUtils;
import cn.getech.data.metadata.entity.CollectionSystemModuleEntity;
import cn.getech.data.metadata.entity.meta.CollectionTableField;
import cn.getech.data.metadata.entity.meta.CollectionTableInfo;
import cn.getech.data.metadata.mapper.BloodRelationshipMapper;
import cn.getech.data.metadata.mapper.CollectionTableField2Mapper;
import cn.getech.data.metadata.mapper.CollectionTableMapper;
import cn.getech.data.metadata.model.excel.CollectionBloodExcel;
import cn.getech.data.metadata.model.excel.CollectionBloodExcelError;
import cn.getech.data.metadata.model.res.CollectionTableFieldRes;
import cn.getech.data.metadata.model.res.collectiontablestatistics.RelationTable;
import cn.getech.data.metadata.service.CollectionBloodService;
import cn.getech.data.metadata.service.CollectionSystemModuleService;
import cn.getech.data.metadata.utils.AtlasLineage;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Service("collectionBloodService")
public class CollectionBloodServiceImpl implements CollectionBloodService {

    private Logger log = LoggerFactory.getLogger(CollectionBloodServiceImpl.class);
    @Autowired
    private CollectionTableField2Mapper collectionTableField2Mapper;
    @Autowired
    private BloodRelationshipMapper bloodRelationshipMapper;
    @Autowired
    private CollectionTableMapper collectionTableMapper;
    @Autowired
    private CollectionSystemModuleService collectionSystemModuleService;
    // atlas 配置信息
    @Value("${data-metadata.atlas.serverUrl:http://10.74.20.69:21001}")
    private String serverUrl;

    @Value("${data-metadata.atlas.baseUrl:/atlas/v2/search/basic}")
    private String baseUrl;

    @Value("${data-metadata.atlas.username:admin}")
    private String username;

    @Value("${data-metadata.atlas.password:admin}")
    private String password;

    @Override
    public int saveBatch(List<CollectionBloodExcel> list, List<CollectionBloodExcelError> failList, Integer tenantId) {

        List<TableRelationshipEntity> ships = new ArrayList<>();
        Map<Integer, CollectionTableInfo> sourceMap = new HashMap<>();
        Map<Integer, CollectionTableInfo> targetMap = new HashMap<>();
        for (CollectionBloodExcel ship : list) {
            String sourceUrl = ship.getSourceIp() + ":" + ship.getSourcePort() + "/" + ship.getSourceName();
            CollectionTableInfo source = null;
            CollectionTableInfo target = null;
            try {
                source = collectionTableMapper.selectOne(
                        new QueryWrapper<CollectionTableInfo>()
                                .like("souce_conf", sourceUrl)
                                .eq("db_name", ship.getSourceName())
                                .eq("table_name", ship.getSourceTableName())
                                .eq("tenant_id", tenantId)
                                .eq("table_type", MetaTableTypeEnum.OUT_TABLE.getValue())
                                .eq("delete_flag", 0)
                );
            } catch (Exception e) {
                failList.add(new CollectionBloodExcelError(ship,
                        "导入失败", "source表[" + ship.getSourceTableName() + "]查询错误" + e.getMessage()));
                continue;
            }
            try {
                String targetUrl = ship.getTargetIp() + ":" + ship.getTargetPort() + "/" + ship.getTargetName();
                target = collectionTableMapper.selectOne(
                        new QueryWrapper<CollectionTableInfo>()
                                .like("souce_conf", targetUrl)
                                .eq("db_name", ship.getTargetName())
                                .eq("table_name", ship.getTargetTableName())
                                .eq("tenant_id", tenantId)
                                .eq("table_type", MetaTableTypeEnum.OUT_TABLE.getValue())
                                .eq("delete_flag", 0)
                );
            } catch (Exception e) {
                failList.add(new CollectionBloodExcelError(ship,
                        "导入失败", "target表[" + ship.getTargetName() + "]查询错误" + e.getMessage()));
                continue;
            }
            if (source == null) {
                failList.add(new CollectionBloodExcelError(ship,
                        "导入失败", "source表[" + ship.getSourceTableName() + "]不存在"));
                continue;
            }
            List<CollectionTableField> fields = collectionTableField2Mapper.selectList(new QueryWrapper<CollectionTableField>()
                    .eq("table_id", source.getId())
                    .eq("field_name", ship.getSourceFiledName()).eq("delete_flag", 0));
            if (CollectionUtils.isEmpty(fields)) {
                failList.add(new CollectionBloodExcelError(ship,
                        "导入失败", "source表[" + ship.getSourceTableName() + "]中字段[" + ship.getSourceFiledName() + "]不存在"));
                continue;
            }
            if (target == null) {
                failList.add(new CollectionBloodExcelError(ship,
                        "导入失败", "target表[" + ship.getTargetTableName() + "]不存在"));
                continue;
            }
            fields = collectionTableField2Mapper.selectList(new QueryWrapper<CollectionTableField>()
                    .eq("table_id", target.getId())
                    .eq("field_name", ship.getTargetFiledName()).eq("delete_flag", 0));
            if (CollectionUtils.isEmpty(fields)) {
                failList.add(new CollectionBloodExcelError(ship,
                        "导入失败", "target表[" + ship.getTargetTableName() + "]中字段[" + ship.getTargetFiledName() + "]不存在"));
                continue;
            }
            TableRelationshipEntity param = new TableRelationshipEntity();
            param.setSourceFieldName(ship.getTargetFiledName());
            param.setSourceTableName(ship.getTargetTableName());
            param.setSourceTableId(target.getTableInfoId());
            param.setSourceCollTableId(target.getId());
            param.setRelationSourceId(source.getSourceId());
            param.setRelationDbname(source.getDbName());
            param.setRelationTableName(source.getTableName());
            param.setRelationFieldName(ship.getSourceFiledName());
            param.setRelationCollTableId(source.getId());
            ships.add(param);
            sourceMap.put(source.getId(), source);
            targetMap.put(target.getId(), target);

        }
        if (CollectionUtils.isNotEmpty(ships)) {
            for (Integer sourceId : sourceMap.keySet()) {
                CollectionTableInfo source = sourceMap.get(sourceId);
                //删掉下游表
                bloodRelationshipMapper.delete(new QueryWrapper<TableRelationshipEntity>()
                        .eq("relation_coll_table_id", source.getId()));
                //删掉上游表
                bloodRelationshipMapper.delete(new QueryWrapper<TableRelationshipEntity>()
                        .eq("source_coll_table_id", source.getId()).or()
                        .eq("source_table_id", source.getTableInfoId()));
            }
            for (Integer targetId : targetMap.keySet()) {
                CollectionTableInfo target = targetMap.get(targetId);
                //删掉上游表
                bloodRelationshipMapper.delete(new QueryWrapper<TableRelationshipEntity>()
                        .eq("source_coll_table_id", target.getId()).or()
                        .eq("source_table_id", target.getTableInfoId()));
                //删掉下游表
                bloodRelationshipMapper.delete(new QueryWrapper<TableRelationshipEntity>()
                        .eq("relation_coll_table_id", target.getId()));
            }
            for (TableRelationshipEntity ship : ships) {
                collectionTableField2Mapper.insertTableRelationship(ship);
            }
        }
        return 0;
    }

    // 同步atlas 的血缘关系
    private void synBloodDataByTableId(Integer tableId) {
        // typeName   查询类型（ 库 /表/ 字段/...  hive表是 hive_table / hive_column）
        CollectionTableInfo table = collectionTableMapper.selectById(tableId);
        if (table != null && MetaTableTypeEnum.OFF_TABLE.getValue().equals(table.getTableType())) {
            List<CollectionTableFieldRes> fields = collectionTableField2Mapper.selectByTableId(tableId);
            //从atlas 中 获取血缘关系
            List<HashMap<String, String>> lineListMap = Lists.newArrayList();
            for (CollectionTableFieldRes field : fields) {
                try {
                    lineListMap.addAll(AtlasLineage.getLineageByTable(serverUrl,
                            username, password, "hive_column", table.getDbName(),
                            table.getTableName().toLowerCase(), field.getFieldName().toLowerCase(), 4));
                } catch (Exception e) {
                   log.info("表{}字段{}无血缘",table.getTableName(),field.getFieldName());
                }
            }
            List<CollectionTableInfo> list = collectionTableMapper.selectList(
                    new QueryWrapper<CollectionTableInfo>()
                            .eq("delete_flag", 0).eq("table_type", 1));
            Map<String, Integer> idsMap = new HashMap<>(list.size());
            for (CollectionTableInfo tableInfo : list) {
                if (tableInfo.getTableName() != null) {
                    idsMap.put(tableInfo.getDbName() + "." + tableInfo.getTableName(), tableInfo.getId());
                }
            }
            List<TableRelationshipEntity> lines = new ArrayList<>();
            for (HashMap<String, String> lineMap : lineListMap) {
                //test.atlas_test_test2.test2_name":"test.atlas_test_test3.test3_name"
                for (String from : lineMap.keySet()) {
                    String dbName = from.split("\\.")[0];
                    String tableName = from.split("\\.")[1];
                    String fieldName = from.split("\\.")[2];
                    String toValue = lineMap.get(from);
                    String toDbName = toValue.split("\\.")[0];
                    String toTableName = toValue.split("\\.")[1];
                    String toFieldName = toValue.split("\\.")[2];
                    Integer fromId = idsMap.get(dbName + "." + tableName);
                    Integer toId = idsMap.get(toDbName + "." + toTableName);
                    if (fromId != null && toId != null) {
                        TableRelationshipEntity line = new TableRelationshipEntity();
                        line.setDataType(1);
                        line.setRelationCollTableId(fromId);
                        line.setRelationDbname(dbName);
                        line.setRelationTableName(tableName);
                        line.setRelationFieldName(fieldName);
                        line.setRelationSourceName("自动解析");
                        line.setRelationSourceId(0);
                        line.setSourceCollTableId(toId);
                        line.setSourceTableName(toTableName);
                        line.setSourceFieldName(toFieldName);
                        List<TableRelationshipEntity> oldList = bloodRelationshipMapper.selectList(
                                new QueryWrapper<TableRelationshipEntity>()
                                        .eq("source_coll_table_id", toId)
                                        .eq("relation_coll_table_id", fromId));
                        if (CollectionUtils.isEmpty(oldList)) {
                            lines.add(line);
                        }
                    }
                }
            }
            if (CollectionUtils.isNotEmpty(lines)) {
                bloodRelationshipMapper.saveList(lines);
            }
        }
    }

    @Override
    public void synBloodData(Integer tableId) {
        ExecutorService pool = Executors.newSingleThreadExecutor();
        pool.execute(() -> {
            try {
                synBloodDataByTableId(tableId);
            } catch (Exception e) {
                log.warn("atlas 血缘拉取失败");
            }
        });
    }

    // 封装上游节点
    private void wrapFromLinkNode(Map<String, List<BloodShip>> toMap,
                                  Map<String, List<BloodShip>> fromMap,
                                  String tableId, List<BloodNode> list,
                                  List<BloodUnion> lineList, BloodNode current) {
        if (toMap.get(tableId) != null && tableId != null) {
            List<BloodShip> ships = toMap.get(tableId);
            for (BloodShip ship : ships) {
                String id = ship.getFrom();
                if (id != null) {
                    BloodUnion line = new BloodUnion(tableId, id,ship.getDataType());
                    lineList.add(line);
                    if (!containsList(list, id)) {
                        BloodNode node = new BloodNode();
                        node.setId(id);
                        if (id.contains("#")) {
                            int intId = Integer.parseInt(id.split("#")[0]);
                            node.setTableId(intId);
                        } else {
                            int intId = Integer.parseInt(id);
                            node.setTableId(intId);
                        }
                        node.setBloodType(1);
                        node.setFieldName(ship.getFromFieldName());
                        node.setTableName(ship.getFromTableName());
                        node.setIco(ship.getDataType().toString());
                        list.add(node);
                        if (toMap.get(id) != null) {
                            node.setFromLayer(current.getFromLayer() + 1);
                            wrapFromLinkNode(toMap, fromMap, id, list, lineList, node);
                        }
                    }
                }
            }
        }
    }

    private boolean containsList(List<BloodNode> list, String tableId) {
        for (BloodNode bloodNode : list) {
            if (bloodNode.getId() != null &&
                    bloodNode.getId().equals(tableId)) {
                return true;
            }
        }
        return false;
    }

    // 封装下游节点
    private void wrapToLinkNode(Map<String, List<BloodShip>> toMap,
                                Map<String, List<BloodShip>> fromMap,
                                String tableId, List<BloodNode> list,
                                List<BloodUnion> lineList, BloodNode current) {

        if (fromMap.get(tableId) != null && tableId != null) {
            List<BloodShip> ships = fromMap.get(tableId);
            for (BloodShip ship : ships) {
                String id = ship.getTo();
                if (id != null) {
                    BloodUnion line = new BloodUnion(id, tableId,ship.getDataType());
                    lineList.add(line);
                    if (!containsList(list, id)) {
                        BloodNode node = new BloodNode();
                        if (id.contains("#")) {
                            int intId = Integer.parseInt(id.split("#")[0]);
                            node.setTableId(intId);
                        } else {
                            int intId = Integer.parseInt(id);
                            node.setTableId(intId);
                        }
                        node.setId(id);
                        node.setBloodType(2);
                        node.setFieldName(ship.getToFieldName());
                        node.setTableName(ship.getToTableName());
                        node.setIco(ship.getDataType().toString());
                        list.add(node);
                        if (fromMap.get(id) != null) {
                            node.setToLayer(current.getToLayer() + 1);
                            wrapToLinkNode(toMap, fromMap, id, list, lineList, node);
                        }
                    }
                }
            }
        }
    }

    private List<BloodNode> distinctNode(List<BloodNode> nodeList) {
        if (CollectionUtils.isNotEmpty(nodeList)) {
            List<BloodNode> list = nodeList.stream().collect(
                    Collectors.collectingAndThen(
                            Collectors.toCollection(() ->
                                    new TreeSet<>(Comparator.comparing(BloodNode::getId)
                                    )), ArrayList::new));
            return list;
        }
        return new ArrayList<>();
    }

    private List<BloodUnion> distinctUnion(List<BloodUnion> nodeList) {
        if (CollectionUtils.isNotEmpty(nodeList)) {
            List<BloodUnion> list = nodeList.stream().collect(
                    Collectors.collectingAndThen(
                            Collectors.toCollection(() ->
                                    new TreeSet<>(Comparator.comparing(BloodUnion::getTo)
                                            .thenComparing(BloodUnion::getFrom))), ArrayList::new));

            return list;
        }
        return new ArrayList<>();
    }

    private Map<Integer, Integer> wrapIdsMap() {
        List<CollectionTableInfo> list = collectionTableMapper.selectList(new QueryWrapper<CollectionTableInfo>()
                .eq("delete_flag", 0).eq("table_type", 1));
        Map<Integer, Integer> idsMap = new HashMap<>(list.size());
        for (CollectionTableInfo tableInfo : list) {
            if (tableInfo.getTableInfoId() != null) {
                idsMap.put(tableInfo.getTableInfoId(), tableInfo.getId());
            }
        }
        return idsMap;
    }

    @Override
    public JSONObject tableRelation(BloodNode current) {
        //synBloodData(Integer.parseInt(current.getId()));
        QueryWrapper<TableRelationshipEntity> paramSource = new QueryWrapper<>();
        List<TableRelationshipEntity> ships = bloodRelationshipMapper.selectList(paramSource);
        List<BloodShip> fieldShips = Lists.newArrayList();
        //离线数仓编辑入口配置的血缘 获取id映射
        Map<Integer, Integer> idsMap = wrapIdsMap();
        for (TableRelationshipEntity ship : ships) {
            if (ship.getSourceCollTableId() == null && ship.getSourceTableId() != null) {
                ship.setSourceCollTableId(idsMap.get(ship.getSourceTableId()));
            }
            if (ship.getRelationCollTableId() != null && ship.getSourceCollTableId() != null) {
                BloodShip fieldShip = new BloodShip(
                        ship.getRelationCollTableId() + "",
                        ship.getSourceCollTableId() + "",
                        ship.getRelationTableName(), ship.getRelationFieldName(),
                        ship.getDataType(), ship.getSourceTableName(), ship.getSourceFieldName()
                );
                fieldShips.add(fieldShip);
            }
        }
        List<BloodUnion> lineList = new ArrayList<>();
        JSONObject data = new JSONObject();
        current.setTableId(Integer.parseInt(current.getId()));
        wrapData(current, fieldShips, lineList, data, 1);
        return data;
    }

    //封装坐标信息
    private void wrapPosition(List<BloodNode> fromList,
                              List<BloodNode> toList,
                              List<BloodNode> nodeList, BloodNode current, JSONObject data) {
        Integer fromLayerMax = 1;
        JSONObject summary = new JSONObject();
        summary.put("fromLayer", 0);
        summary.put("toLayer", 0);
        if (CollectionUtils.isNotEmpty(fromList)) {
            fromList = fromList.stream().filter(s -> !s.getId().equals(current.getId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(fromList)) {
                BloodNode fromLayer = fromList.stream()
                        .max(Comparator.comparing(BloodNode::getFromLayer)).get();
                summary.put("fromLayer", fromLayer.getFromLayer());
                fromLayerMax = fromLayer.getFromLayer();
            }
        }
        if (CollectionUtils.isNotEmpty(toList)) {
            toList = toList.stream().filter(s -> !s.getId().equals(current.getId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(toList)) {
                BloodNode toLayer = toList.stream()
                        .max(Comparator.comparing(BloodNode::getToLayer)).get();
                summary.put("toLayer", toLayer.getToLayer());
            }
        }
        int factor = 120;//坐标横向 因子
        int topFactor = 100;// 坐标竖向 因子
        summary.put("fromNum", fromList.size());
        summary.put("toNum", toList.size());
        data.put("summary", summary);
        for (BloodNode bloodNode : fromList) {
            bloodNode.setLeftInt((fromLayerMax - bloodNode.getFromLayer()) * 2 * factor);
        }
        Map<Integer, List<BloodNode>> fromListMap = fromList.stream().filter(s -> s.getFromLayer() != null)
                .collect(Collectors.groupingBy(BloodNode::getFromLayer));
        Map<Integer, List<BloodNode>> toListMap = toList.stream().filter(s -> s.getToLayer() != null)
                .collect(Collectors.groupingBy(BloodNode::getToLayer));
        for (Integer layer : fromListMap.keySet()) {
            for (int i = 0; i < fromListMap.get(layer).size(); i++) {
                fromListMap.get(layer).get(i).setTopInt(topFactor + i * topFactor);
            }
        }
        for (Integer layer : toListMap.keySet()) {
            for (int i = 0; i < toListMap.get(layer).size(); i++) {
                toListMap.get(layer).get(i).setTopInt(topFactor + topFactor * i);
            }
        }
        Integer preLeft = factor;
        Integer preTop = factor;
        if (CollectionUtils.isNotEmpty(fromList)) {
            BloodNode fromLayer = fromList.stream().max(Comparator.comparing(BloodNode::getLeftInt)).get();
            preLeft = fromLayer.getLeftInt();
        }

        if (CollectionUtils.isNotEmpty(fromList)) {
            BloodNode fromLayer = fromList.stream().max(Comparator.comparing(BloodNode::getTopInt)).get();
            preTop = fromLayer.getTopInt();
        }
        if (CollectionUtils.isNotEmpty(toList)) {
            BloodNode fromLayer = toList.stream().max(Comparator.comparing(BloodNode::getTopInt)).get();
            if (fromLayer.getTopInt() > preTop) {
                preTop = fromLayer.getTopInt();
            }
        }
        current.setLeftInt(preLeft + 2 * factor);
        current.setTopInt(preTop);
        for (Integer integer : fromListMap.keySet()) {
            if (fromListMap.get(integer).size() > 1) {
                current.setTopInt(preTop / 2);
            }
        }
        for (Integer integer : toListMap.keySet()) {
            if (toListMap.get(integer).size() > 1) {
                current.setTopInt(preTop / 2);
            }
        }
        for (BloodNode bloodNode : toList) {
            bloodNode.setLeftInt(current.getLeftInt() + (bloodNode.getToLayer() * 3 * factor) / 2);
        }
        nodeList.addAll(fromList);
        nodeList.add(current);
        nodeList.addAll(toList);
    }

    private List<BloodNode> wrapData(BloodNode current, List<BloodShip> fieldShips, List<BloodUnion> lineList,
                                     JSONObject data, int type) {
        Map<String, List<BloodShip>> toListMap = fieldShips.stream().filter(s -> s.getTo() != null)
                .collect(Collectors.groupingBy(BloodShip::getTo));
        Map<String, List<BloodShip>> fromListMap = fieldShips.stream().filter(s -> s.getFrom() != null)
                .collect(Collectors.groupingBy(BloodShip::getFrom));
        List<BloodNode> fromList = new ArrayList<>();
        List<BloodNode> toList = new ArrayList<>();
        wrapFromLinkNode(toListMap, fromListMap, current.getId(), fromList, lineList, current);
        wrapToLinkNode(toListMap, fromListMap, current.getId(), toList, lineList, current);
        List<BloodNode> nodeList = new ArrayList<>();
        wrapPosition(fromList, toList, nodeList, current, data);
        for (BloodNode bloodNode : nodeList) {
            if (bloodNode.getId().equals(current.getId())) {
                bloodNode.setBloodType(0);
            }
        }
        if (type == 1) {//表血缘
            List<Integer> toIds = toList.stream()
                    .filter(s->!s.getId().equals(current.getId()))
                    .filter(s -> s.getTableId() != null)
                    .map(BloodNode::getTableId).collect(Collectors.toList());
            List<Integer> fromIds = fromList.stream()
                    .filter(s->!s.getId().equals(current.getId()))
                    .filter(s -> s.getTableId() != null)
                    .map(BloodNode::getTableId).collect(Collectors.toList());
            for (BloodUnion bloodUnion : lineList) {
                if (bloodUnion.getFrom().equals(current.getId())
                && bloodUnion.getTo().equals(current.getId())
                ) { //自旋节点标记自动
                    toIds.add(current.getTableId());
                    fromIds.add(current.getTableId());
                    current.setIco("1");
                }
            }

            if (CollectionUtils.isNotEmpty(toIds)) {
                List<RelationTable> toTableList = collectionTableMapper.selectMetaTable(toIds);
                data.put("toTableList", toTableList);
            } else {
                data.put("toTableList", new ArrayList<>());
            }
            if (CollectionUtils.isNotEmpty(fromIds)) {
                List<RelationTable> fromTableList = collectionTableMapper.selectMetaTable(fromIds);
                data.put("fromTableList", fromTableList);
            } else {
                data.put("fromTableList", new ArrayList<>());
            }
            CollectionTableInfo currentTable = collectionTableMapper.selectById(current.getTableId());
            data.put("lineList", distinctUnion(lineList));
            List<CollectionTableFieldRes> fields = collectionTableField2Mapper.selectByTableId(Integer.parseInt(current.getId()));
            data.put("currentTable",currentTable);
            data.put("currentFields", fields);
        }
        Map<String, Integer> icoMap = new HashMap<>();
        for (BloodUnion bloodUnion : lineList) {
            BloodUnion line = collectionTableMapper.selectException(bloodUnion);
            if (line != null) {
                bloodUnion.setException(YesOrNoEnum.YES.getValue());
            }
            icoMap.put(bloodUnion.getTo(), bloodUnion.getDataType());
        }
        List<BloodNode> nodes = distinctNode(nodeList);
        for (BloodNode node : nodes) {
            Integer ico = icoMap.get(node.getId());
            if (YesOrNoEnum.YES.getValue().equals(ico)) {
                node.setIco(ico.toString());
            }
        }
        data.put("nodeList", nodes);
        data.put("lineList", distinctUnion(lineList));
        return nodeList;
    }

    @Override
    public JSONObject tableFieldRelation(BloodNode current) {
        QueryWrapper<TableRelationshipEntity> paramSource = new QueryWrapper<>();
        List<TableRelationshipEntity> ships = bloodRelationshipMapper.selectList(paramSource);
        List<BloodShip> fieldShips = Lists.newArrayList();
        //离线数仓编辑入口配置的血缘 获取id映射
        Map<Integer, Integer> idsMap = wrapIdsMap();
        for (TableRelationshipEntity ship : ships) {
            if (ship.getSourceCollTableId() == null && ship.getSourceTableId() != null) {
                ship.setSourceCollTableId(idsMap.get(ship.getSourceTableId()));
            }
            if (ship.getRelationCollTableId() != null && ship.getSourceCollTableId() != null) {
                BloodShip fieldShip = new BloodShip(
                        ship.getRelationCollTableId() + "#" + ship.getRelationFieldName(),
                        ship.getSourceCollTableId() + "#" + ship.getSourceFieldName(),
                        ship.getRelationTableName(), ship.getRelationFieldName(),
                        ship.getDataType(), ship.getSourceTableName(), ship.getSourceFieldName()
                );
                fieldShips.add(fieldShip);
            }

        }
        List<BloodUnion> lineList = new ArrayList<>();
        JSONObject data = new JSONObject();
        current.setId(current.getId() + "#" + current.getFieldName());
        List<BloodNode> nodeList = wrapData(current, fieldShips, lineList, data, 2);
        for (BloodNode bloodNode : nodeList) {
            bloodNode.setType("field");
        }
        return data;
    }

    @Override
    public CollectionTableInfo getNodeInfo(Integer id) {
        CollectionTableInfo currentTable = collectionTableMapper.selectMetaTableInfo(id);
        List<CollectionSystemModuleEntity> moduleList = collectionSystemModuleService.list();
        String moduleName = ModuleUtils.getAllPath(moduleList, currentTable.getOwnModule());
        currentTable.setModuleName(moduleName);
        return currentTable;
    }

    @Override
    public void relationDelete(BloodUnion current) {
        bloodRelationshipMapper.deleteLineException(current);
    }

    @Override
    public void relationSave(BloodUnion current) {
        bloodRelationshipMapper.saveLineException(current);
    }
}
